//
//  Worker.swift
//  Auto114
//
//  Created by yb on 2020/8/24.
//  Copyright © 2020 RMCtl. All rights reserved.
//

import Foundation

class Worker {
    var name = ""
    
    var hospitalCode = "129"
    var firstDeptCode = "09faeb35e41d5693dfe8733e1dbe2c98"
    var secondDeptCode = "200001196"
//    var secondDeptCode = "200001110" //专家
    var targetDate = "2020-09-11"
    var doctorName = "罗卫"
    var verifyPhoneCode = true
    
//    var hospitalCode = "H08110008"
//    var firstDeptCode = "mn_fst_ek_613308"
//    var secondDeptCode = "1162"
//    var targetDate = "2020-08-31"
//    var doctorName = ""
    
    var cardType = "SOCIAL_SECURITY"
    var cardNumber = "114542878009"
    var phoneNumber = "18611814099"
    var phoneBase64 = "DQp9B7hh46dTw-xHtNoWLA=="
//    var phoneNumber = "18611814099" //test
//    var cardNumber = "114542878009" //test

    var isFinish = false
    var isNotNeedGetProductList = false
    var takingOrder = false
    var shouldAutoRefreshProductList = false
    
    var getProductListRequestCount = 0 {
        didSet {
            if getProductListRequestCount == 0 && !isNotNeedGetProductList && shouldAutoRefreshProductList {
                getProduct()
            }
        }
    }
    
    func work() {
        LogViewUtility.log("work: \(name)")
        plantCookies {
            self.getOpenTime { (refreshMS) in
                LogViewUtility.log("schedual work at:\(Date().timeIntervalSince1970*1000+refreshMS) after \(refreshMS/1000)s (\(refreshMS/1000/60)min): \(self.name)")

                func schedualTimer(offset: Double, block: @escaping () -> Void) {
                    var t: DispatchSourceTimer! = DispatchSource.makeTimerSource(queue: .main)
                    let target = DispatchTime.now() + (refreshMS+offset)/1000
                    t.schedule(deadline: target, leeway: .microseconds(0))
                    t.setEventHandler {
                        block()
                        t = nil
                    }
                    t.resume()
                }
                
                func schedualGetProduct(offset: Double) {
                    schedualTimer(offset: offset) {
                        self.getProduct()
                    }
                }
                schedualTimer(offset: -400) {
                    self.preSendCode()
                }
                schedualGetProduct(offset: -2000)
                schedualGetProduct(offset: -1000)
                schedualGetProduct(offset: -300)
                schedualGetProduct(offset: -150)
                schedualTimer(offset: -50) {
                    self.getProduct()
                    self.shouldAutoRefreshProductList = true
                }

            }
        }
    }
    
    func plantCookies(then: @escaping () -> Void) {
        getUrl(baseUrl+"hospital/list", params: ["_time": ts,
                                                 "keywords":"",
                                                 "pageNo":1,
                                                 "pageSize": "15",
                                                 "sortType": "COMPREHENSIVE",
                                                 "areaId":0]) { (resp) in
            LogViewUtility.log("prepare work done: \(self.name)")
            then()
        }
    }
    
    func getOpenTime(then: @escaping (Double) -> Void) {
        postUrl(baseUrl+"product/list?_time=\(ts)", params: [
            "hosCode": hospitalCode,
            "firstDeptCode": firstDeptCode,
            "secondDeptCode": secondDeptCode
        ]) { (resp) in
            guard let json = resp.result.any as? [String: Any],
                let resCode = json["resCode"] as? Int, resCode == 0,
                let data = json["data"] as? [String: Any],
                let fhTimestamp = data["fhTimestamp"] as? Int,
                let refreshMS = data["refreshMilliseconds"] as? Int else {
                    self.isFinish = true
                    LogViewUtility.log("get product/list error: \(self.name)")
                return
            }
            
            then(3000)   //test only
            return;
            
            let nowTS = Int(Date().timeIntervalSince1970 * 1000)
            if nowTS + refreshMS > fhTimestamp {
                then(Double(fhTimestamp-nowTS))
            } else {
                then(Double(refreshMS))
            }
        }
    }
    
    func getProduct() {
        guard !isFinish && !takingOrder && !isNotNeedGetProductList else {
            return
        }
        LogViewUtility.log("getProduct: \(self.name)")
        getProductListRequestCount += 1
        self.getProductList { (data) in
            defer {
                self.getProductListRequestCount -= 1
            }
            guard !self.isFinish else {
                LogViewUtility.log("getProductList returned!")
                return
            }
            guard let data = data else {
                LogViewUtility.log("getProductList fail: \(self.name)")
                return
            }
            guard !data.isEmpty else {
                LogViewUtility.log("getProductList empty: \(self.name)")
                return
            }
            self.isNotNeedGetProductList = true
            guard let product = self.findTargetProduct(in: data) else {
                //有数据但是没有对应医生，挂号失败
                LogViewUtility.log("getProductList no product and stop: \(self.name)")
                self.isFinish = true
                return
            }
            LogViewUtility.log("getProductList success: \(self.name)")
            self.takeOrder(product: product)
        }
        
    }
    
    func takeOrder(product: Product) {
        guard !takingOrder else {
            return
        }
        takingOrder = true
        LogViewUtility.log("takeOrder: \(name)")
        if verifyPhoneCode {
            sendCode(productKey: product.key) { (success) in
                guard success else {
                    LogViewUtility.log("send code fail: \(self.name)")
                    return
                }
                LogViewUtility.log("send code success: \(self.name)")
                InputPhoneCode.shared.getUserInput { (code) in
                    self.saveOrder(product: product, code: code)
                }
            }
        } else {
            saveOrder(product: product)
        }
        
        
    }
    
    func saveOrder(product: Product, code: String = "") {
        comfirmProduct(product: product) { (suc) in
            LogViewUtility.log("confirmProduct: \(self.name), \(suc)")
        }
        survey { (result) in
            LogViewUtility.log("survey: \(self.name), \(result)")
        }
        order(product: product, code: code) { (suc) in
            LogViewUtility.log("order result: \(self.name), \(suc)")
            self.takingOrder = false
            self.isFinish = true
        }
    }
    

}
